package com.thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * 1. 创建队列LinkedBlockingDeque
 * 2. 创建指定数量的无限循环线程
 * 3. 向队列插入Runnable类型任务
 * 4. 死循环中不断读取队列
 */
public class MyExecuter {

    /**
     * 核心线程数个队列数量
     */
    private List<MyThread> myThreadList;

    /**
     * 队列对象
     */
    private BlockingDeque<Runnable> blockingDeque;

    /**
     * 队列长度限制
     */
    private int queueCount;

    /**
     * 核心线程池数
     */
    private int coreThreadCount;

    /**
     * 最大线程池数
     */
    private int maxThreadCount;

    private boolean startThread = true;
    /**
     * 构造方法初始化
     * @param coreThreadCount   核心线程池数量
     * @param queueCount         队列数量
     * @param maxThreadCount    最大线程池数量
     */
    public MyExecuter(int coreThreadCount, int queueCount, int maxThreadCount){

        this.queueCount = queueCount;
        this.coreThreadCount = coreThreadCount;
        this.maxThreadCount = maxThreadCount;

        // 1. 初始化队列
        blockingDeque = new LinkedBlockingDeque<Runnable>(queueCount);

        // 2. 初始化线程
        myThreadList = new ArrayList<MyThread>(coreThreadCount);
        for(int i = 0; i < coreThreadCount; i++){
            new MyThread().start();
        }
    }

    class MyThread extends Thread{
        @Override
        public void run() {

            // 4. 死循环中不断读取队列，当为false或者队列为空时关闭
            while (startThread || blockingDeque.size() > 0){
                // 取出队列最开始的元素，并从队列中删除
                Runnable poll = blockingDeque.poll();
                if(poll != null){
                    poll.run();
                }

            }

        }
    }

    /**
     * 向队列中插入Runnable任务
     */
    public boolean execute(Runnable runnable){
        // 3. 向队列插入Runnable类型任务
        return blockingDeque.offer(runnable);
    }


    public static void main(String[] args) {
        MyExecuter myExecuter = new MyExecuter(2, 2, 4);

        for(int i = 0; i < 10; i++){
            final int ss = i;
            myExecuter.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "," + ss);
                }
            });
        }
    }
}

